package cn.edu.stu.syllabus.library.detail;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import cn.edu.stu.syllabus.R;
import cn.edu.stu.syllabus.datas.Information;
import cn.edu.stu.syllabus.datas.RequestState;
import cn.edu.stu.syllabus.di.scope.FragmentScoped;
import cn.edu.stu.syllabus.library.list.QueryBooksListPresenter;
import cn.edu.stu.syllabus.repository.booklocate.BookLocateConverter;
import cn.edu.stu.syllabus.repository.booklocate.local.BookLocateEntry;
import cn.edu.stu.syllabus.repository.library.BookStarDataRepository;
import cn.edu.stu.syllabus.repository.library.local.BookEntry;
import cn.edu.stu.syllabus.utils.ExtraNameJoiner;
import cn.edu.stu.syllabus.utils.RxSchedulerUtils;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.functions.Func1;
import rx.subscriptions.CompositeSubscription;

import static cn.edu.stu.syllabus.utils.NullPointerUtils.checkNotNull;

/**
 * Created by liyujie on 2017/3/28.
 */

@FragmentScoped
public class BookDetailPresenter implements BookDetailContract.Presenter {

    private final BookDetailContract.View mView;

    private final BookEntry mBookEntry;

    private final BookStarDataRepository mBookStarDataRepository;

    private CompositeSubscription mSubscriptions;

    public static final String EXTRA_BOOK_LOCATES = ExtraNameJoiner.join(
            QueryBooksListPresenter.class, "mBookLocateEntries"
    );

    private static final String EXTRA_REQUEST_STATE = ExtraNameJoiner.join(
            QueryBooksListPresenter.class, "mRequestState"
    );

    private int mRequestState;

    private List<BookLocateEntry> mBookLocateEntries;

    @Inject
    public BookDetailPresenter(BookDetailContract.View view,
                               BookStarDataRepository bookStarDataRepository,
                               BookEntry bookEntry) {
        mView = checkNotNull(view);
        mBookStarDataRepository = checkNotNull(bookStarDataRepository);
        mBookEntry = checkNotNull(bookEntry);
        mSubscriptions = new CompositeSubscription();
    }

    @Inject
    void setupListener() {
        mView.setPresenter(this);
    }

    @Override
    public void subscribe() {
        setupInformation();

        if (mBookLocateEntries == null) {
            if (RequestState.isError(mRequestState)) {
                mView.showError();
            } else {
                mRequestState = RequestState.REQUEST_FIRST;
                loadBookLocates();
            }
        } else {
            mView.showBookLocate(mBookLocateEntries);
        }
    }

    @Override
    public void unsubscribe() {
        mSubscriptions.unsubscribe();
    }

    private void setupInformation() {
        List<Information> informations = new ArrayList<>();
        informations.add(new Information(R.drawable.ic_book, "书名", mBookEntry.getName()));
        informations.add(new Information(R.drawable.ic_author, "作者", mBookEntry.getAuthor()));
        informations.add(new Information(R.drawable.ic_press, "出版社", mBookEntry.getPress()));
        informations.add(new Information(R.drawable.ic_press_date, "出版时间", mBookEntry.getPressDate()));
        mView.showInformation(informations);
    }

    @Override
    public void parseHtml(String html) {
        Subscription subscription = Observable.just(html)
                .map(new Func1<String, List<BookLocateEntry>>() {
                    @Override
                    public List<BookLocateEntry> call(String s) {
                        return BookLocateConverter.convert(s);
                    }
                })
                .compose(RxSchedulerUtils.<List<BookLocateEntry>>io2mainSchedulersTransformer())
                .subscribe(new Subscriber<List<BookLocateEntry>>() {

                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        mView.showError();
                        mRequestState = RequestState.REQUEST_ERROR;
                    }

                    @Override
                    public void onNext(List<BookLocateEntry> bookLocateEntries) {
                        mBookLocateEntries = bookLocateEntries;
                        mView.showBookLocate(bookLocateEntries);
                        mRequestState = RequestState.REQUEST_SUCCESS;
                    }
                });
        mSubscriptions.add(subscription);
    }

    @Override
    public void loadBookLocates() {
        mView.showLoading();
        mView.loadUrl(mBookEntry.getUrl());
    }

    @Override
    public void starBook() {
        mBookStarDataRepository.starBookEntry(mBookEntry);
    }

    @Override
    public void unstarBook() {
        mBookStarDataRepository.unstarBookEntry(mBookEntry);
    }

    @Override
    public boolean isStarBook() {
        return mBookStarDataRepository.isExistEntry(mBookEntry);
    }

    @Override
    public Map<String, Object> getStoreData() {
        Map<String, Object> storeData = new HashMap<>();
        storeData.put(EXTRA_BOOK_LOCATES, mBookLocateEntries);
        storeData.put(EXTRA_REQUEST_STATE, mRequestState);
        return storeData;
    }

    @Override
    public void restoreData(Map<String, Object> storeData) {
        mBookLocateEntries = (List<BookLocateEntry>) storeData.get(EXTRA_BOOK_LOCATES);
        mRequestState = (int) storeData.get(EXTRA_REQUEST_STATE);
    }
}
